﻿using System;
using Plugins.Interfaces;

namespace Plugins.StateMachines
{
    [Serializable]
    public abstract class PluginBaseState : IPluginStateHandler
    {
        private object _value;
        private PluginBaseState _init;
        private PluginBaseState _next;
        private PluginBaseState _current;

        protected PluginBaseState(PluginBaseState init)
        {
            _init = init;
            _current = _init;
        }

        protected void BaseSetNextState(IPluginState state) { _next = state as PluginBaseState; }
        protected void BaseSetNextState<T>(IPluginState<T> state) { _next = state as PluginBaseState; }
        protected void BaseSetNextState(PluginBaseState state) { _next = state; }
        protected void BaseSetCurrentState(IPluginState state) { _current = state as PluginBaseState; }
        protected void BaseSetCurrentState<T>(IPluginState<T> state) { _current = state as PluginBaseState; }
        protected void BaseSetCurrentState(PluginBaseState state) { _current = state; }

        protected bool BaseMoveNext()
        {
            /// this._current --> this
            return BaseRunNextState(_current, this);
        }
        protected bool RunNextState()
        {
            /// this._next --> this._next
            return BaseRunNextState(_next, _next);
        }
        public virtual bool Run()
        {
            /// this._current --> _next
            return BaseRunNextState(_current, _next);
        }

        protected bool BaseRunNextState(PluginBaseState state1, PluginBaseState state2)
        {
            if (state1 != null)
            {
                state1.BaseSetNextState(state2);
                return state1.Run();
            }
            return false;
        }

        protected virtual void Reset()
        {
            _current = _init;
            _value = null;
        }

        protected PluginBaseState CurrentState { get { return _current; } }
        public void Link(PluginBaseState state)
        {
            _init = state;
            _current = _init;
        }
        protected void SetNextState(PluginBaseState state)
        {
            _next.BaseSetCurrentState(state);
        }
        protected void SetNextValue(object obj)
        {
            _next.BaseSetValue(obj);
        }
        protected void BaseSetValue(object value)
        {
            _value = value;
        }
        protected object Value { get { return _value; } }
    }
}
